import { defineStore } from 'pinia'
import { isExternal } from '@/utils/is.ts'
import { hyphenate } from '@vueuse/core'
import { RouteRecordRaw } from 'vue-router'
import { PermissionDto as Permission } from '@/api/permission.ts'
import utils from 'xe-utils'

export interface MenuItem {
  label: string
  shortLabel: string | null
  key: string
  path: string
  originPath: string
  icon: string
  order: number
  children?: MenuItem[]
}

export const usePermissionStore = defineStore('permission', {
  state: (): {
    permissions: Permission[]
    accessRoutes: RouteRecordRaw[]
    menus: MenuItem[]
  } => ({
    accessRoutes: [],
    permissions: [],
    menus: [],
  }),
  actions: {
    resetPermission() {
      this.$reset()
    },
    setPermissions(permissions: Permission[]) {
      this.permissions = utils.toTreeArray(permissions)
      this.menus = permissions
        .filter((item) => item.type == 'MENU')
        .map((item) => this.getMenuItem(item)!)
        .filter((item) => !!item)
        .sort((a, b) => b!.order - a!.order)
    },
    getMenuItem(item: Permission, parent?: MenuItem) {
      const route = this.generateRoute(item, item.show ? null : parent?.key)
      if (item.enable && route.path && !route.path.startsWith('http')) this.accessRoutes.push(route)

      const menuItem: MenuItem = {
        label: route.meta?.title as string,
        shortLabel: item.shortName,
        key: route.name as string,
        path: route.path,
        originPath: route.meta?.originPath as string,
        icon: route.meta?.icon as string,
        children: [],
        order: item.weight ?? 0,
      }

      if (!item.show) {
        if (item.children && item.children?.length > 0) {
          item.children.forEach((child) => {
            this.getMenuItem(child, menuItem)
          })
        }

        return
      }

      const children = item.children?.filter((item) => item.type === 'MENU') || []
      if (children.length) {
        menuItem.children = children
          .map((child) => this.getMenuItem(child, menuItem)!)
          .filter((item) => !!item)
          .sort((a, b) => b!.order - a!.order)
        // if (!menuItem.children.length) delete menuItem.children
      }

      return menuItem
    },
    generateRoute(item: Permission, parentKey?: string | null): RouteRecordRaw {
      let originPath = undefined

      if (item.path && isExternal(item.path)) {
        originPath = item.path
        item.component = `/src/views/iframe/index.vue`
        item.path = `/iframe/${hyphenate(item.code!)}`
      }

      return {
        name: item.code!,
        path: item.path!,
        redirect: item.redirect!,
        component: item.component as any,
        meta: {
          originPath,
          icon: item.icon + '?mask',
          title: item.name,
          layout: item.layout,
          back: item.back,
          keepAlive: item.keepAlive,
          parentKey,
          buttons: item.children
            ?.filter((item) => item.type == 'BUTTON')
            .map((item) => ({
              code: item.code,
              name: item.name,
            })),
        },
      }
    },
    validateMenuPath(path: string) {
      return this.accessRoutes.findIndex((menu: RouteRecordRaw) => menu.path == path) > -1
    },
  },
  getters: {
    getValidRoute(state) {
      return state.accessRoutes[0]
    },
  },
})
